1. /* sifisdiv.cpp by K.Tsuru */
  2. // function ID = 428 BRADIX
  3. /**************************
  4. SInteger class
  5. It divides SInteger 'm' by an integer 'x'(ulong) (i.e. quot = m/x)
  6. and returns the remainder.
  7. ***************************/
  8. #ifndef SN_H
  9. #include "sn.h"
  10. #endif
  11. static const char* func = "IsDiv";
  12. long IsDiv(const SInteger& m, ulong x, SInteger& quot){
  13. if( !x ) m.SetError(m.DIVIDED_BY_ZERO, func, 428);
  14. //When &m == &quot and quot/x == 0 it yields m = 0.Then it keeps the sign.
  15. //The sign of m is necessary to return the remainder.
  16. int msgn = m.Sign(428);
  17. if(x == 1uL || !msgn){
  18. quot = m; return 0; //remainder=0
  19. }
  20. const ulong mt = m.SlOpMaxValue();
  21. if(x > mt) m.SetError(m.OUT_OF_RANGE, func, 428);
  22. int qh = (int)m.Head(), qt = (int)m.Tail();
  23. if(qh <= 1){//The figures of m is one or two.
  24. // s <= (B-1)*B+(B-1) = B^2 -1 < LONG_MAX
  25. long s = (long)m[1]*BRADIX + (long)m[0]; //It can be convert to the long value.
  26. quot.SetLong(s/(long)x); // size = 4
  27. s = s%(long)x;
  28. return msgn > 0 ? s : -s; //The sign of remainder is the same as that of m.
  29. }
  30. if(&m != &quot){
  31. //When &m == &quot it must not be executed / is not necessary.
  32. if(quot.Size() < m.Size()) quot.valloc(m.Size(), -1);
  33. //It fills the lower part with zero.
  34. if(qt) quot.figure.clear(quot.aTail, uint(qt-1));
  35. quot.figure.clear(uint(qh + 1));
  36. }
  37. const fType* mv = m.ReadFigures();
  38. fType* qv = quot.figure.Elements();
  39. ulong t = 0;
  40. #ifndef NDEBUG
  41. quot.figure(qh); m.figure(qh);
  42. #endif
  43. //Taking more a few figures the remainder maybe becomes zero.
  44. if(qt > 4) qt -= 4;
  45. int i;
  46. for(i = qh; i >= qt ; i--) {
  47. // t = (t << BRADIX_BITS) | mv[i]; same speed
  48. t = (t << BRADIX_BITS) + mv[i];
  49. qv[i] = fType(t/x);
  50. t = t - qv[i]*x; //faster than t %= x; t < x
  51. }
  52. if((i>=0) && t){
  53. // for( ; (i >= 0) && t; i--){
  54. for( ; i >= 0; i--){
  55. t = (t << BRADIX_BITS);
  56. qv[i] = fType(t/x);
  57. t = t - qv[i]*x;
  58. }
  59. }
  60. qt = (i >= 0) ? i : 0;
  61. //The lower part has been filled by zeros.
  62. //When the remainder is zero and &m == &quot, figure[k] = 0 for k < qt.
  63. //Then it is not necessary to fill zeros.
  64. //It checks the figure position. It ends by a few figures.
  65. while( (qh >= 0) && !qv[qh] ) qh--;
  66. while( (qt <= qh) && !qv[qt]) qt++;
  67. if( (qh <= 0) && !qv[0] ){
  68. quot.SetZero(); //It becomes zero.
  69. } else {
  70. #ifndef NDEBUG
  71. assert(qh >= qt);
  72. #endif
  73. //When &quot == &m the figure position must be decided before the sign.
  74. //If not, an error will occur.
  75. quot.aHead = (uint)qh;
  76. quot.aTail = (uint)qt;
  77. quot.SetSign(m.Sign(428));
  78. }
  79. //It reduces the size. This is necessary because the CopyValue() is not called.
  80. if( 2u*(quot.aHead+1) <= quot.figure.size() ) quot.DoCutDown();
  81. long rem = (long)t; // t < x <= SlOpMaxValue() < LONG_MAX
  82. return msgn > 0 ? rem : -rem; //The sign of remainder is the same as that of "m".
  83. }

sifisdiv.cpp : last modifiled at 2017/03/13 14:31:59(2,896 bytes)
created at 2016/04/25 14:53:17
The creation time of this html file is 2017/10/25 11:09:45 (Wed Oct 25 11:09:45 2017).